/*
 * @Copyright: 2023 - 2023 www.hoperun.com Inc. All rights reserved.
 */

package com.lifeservice.wxapi;

import com.lifeservice.common.core.domain.AjaxResult;
import com.lifeservice.common.core.redis.RedisCache;
import com.lifeservice.common.core.redis.RedisLockUtil;
import com.lifeservice.common.exception.ServiceException;
import com.lifeservice.common.utils.SnowFlakeUtil;
import com.lifeservice.common.utils.StringUtils;
import com.lifeservice.console.domain.LifeOrder;
import com.lifeservice.console.domain.LifeSupplierInfo;
import com.lifeservice.console.domain.LifeWorkClass;
import com.lifeservice.console.domain.appvo.AppBaseQueryVo;
import com.lifeservice.console.domain.appvo.AppOrderInfo;
import com.lifeservice.console.domain.appvo.AppSubscribeVo;
import com.lifeservice.console.mapper.LifeOrderMapper;
import com.lifeservice.console.mapper.LifeSupplierInfoMapper;
import com.lifeservice.console.mapper.LifeWorkClassMapper;
import com.lifeservice.util.LifeServiceConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author liu_yifeng
 * @function 订单信息wx接口
 * @date 2023/2/27 10:16
 */
@RestController
@RequestMapping("/wx/order")
@Slf4j
public class WxOrderController {
    @Autowired
    private LifeOrderMapper lifeOrderMapper;

    @Autowired
    private LifeWorkClassMapper lifeWorkClassMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private RedisLockUtil redisLockUtil;

    @Autowired
    private LifeSupplierInfoMapper lifeSupplierInfoMapper;

    @PostMapping("/list")
    public AjaxResult listByUserInfo(@RequestBody AppBaseQueryVo appBaseQueryVo) {
        LifeOrder order = new LifeOrder();
        order.setUserId(appBaseQueryVo.getUserId());
        List<Integer> showStatusList = Arrays.asList(LifeServiceConstants.ORDER_STATUS_NOMAL, LifeServiceConstants.ORDER_STATUS_CANCEL, LifeServiceConstants.ORDER_STATUS_COMPLETE);
        order.setStatusList(showStatusList);
        List<LifeOrder> orderList = lifeOrderMapper.selectLifeOrderList(order);
        List<LifeOrder> finalList = new LinkedList<>();
        finalList.addAll(orderList.stream().filter(entity -> StringUtils.isNotEmpty(entity.getServeDay())).collect(Collectors.toList()));
        finalList.addAll(orderList.stream().filter(entity -> StringUtils.isEmpty(entity.getServeDay())).peek(vo -> resetOrderInfo(vo)).collect(Collectors.toList()));
        return AjaxResult.success(finalList);
    }

    private void resetOrderInfo(LifeOrder order) {
        order.setServeDay("-");
        order.setServeWeek("");
        order.setWorkTime("");
        order.setBuildingName("服务已取消");
        order.setBuildingDetailAddress("服务已取消");
        order.setStatus(0);
    }

    @PostMapping("/subscribe")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult subscribe(@RequestBody AppSubscribeVo subscribeVo) {
        String userId = subscribeVo.getUserId();
        String supplierId = subscribeVo.getSupplierId();
        String workClassId = subscribeVo.getWorkClassId();
        LifeOrder checkExsit = new LifeOrder();
        checkExsit.setUserId(userId);
        checkExsit.setSupplierId(supplierId);
        checkExsit.setWorkClassId(workClassId);
        List<LifeOrder> result = lifeOrderMapper.selectLifeOrderList(checkExsit);
        if (StringUtils.isNotEmpty(result)) {
            LifeOrder order = result.get(0);
            if (LifeServiceConstants.ORDER_STATUS_NOMAL == order.getStatus()) {
                return AjaxResult.error("此时间段您已有预约！请重新预约其他时间段！");
            } else if (LifeServiceConstants.ORDER_STATUS_COMPLETE == order.getStatus() || LifeServiceConstants.ORDER_STATUS_DELETED == order.getStatus()) {
                log.info("这个时间段已经完成一次预约，可以新增一个预约");
            } else {
                AppOrderInfo appOrderInfo = new AppOrderInfo();
                appOrderInfo.setOrderId(order.getId());
                appOrderInfo.setGuestName(subscribeVo.getGuestName());
                appOrderInfo.setGuestPhone(subscribeVo.getGuestPhone());
                appOrderInfo.setGuestRemark(subscribeVo.getGuestRemark());
                return reSubscribe(appOrderInfo);
            }
        }
        LifeOrder order = new LifeOrder();
        order.setId(SnowFlakeUtil.getInstance().nextId());
        order.setSupplierId(supplierId);
        order.setUserId(userId);
        order.setWorkClassId(workClassId);
        order.setCreateBy(userId);
        order.setGuestName(subscribeVo.getGuestName());
        order.setGuestPhone(subscribeVo.getGuestPhone());
        order.setGuestRemark(subscribeVo.getGuestRemark());
        order.setCreateTime(new Date());
        order.setUpdateTime(new Date());
        order.setStatus(LifeServiceConstants.ORDER_STATUS_NOMAL);
        dealWorkClassStock(workClassId, true);
        lifeOrderMapper.insertLifeOrder(order);
        LifeSupplierInfo supplierInfo = lifeSupplierInfoMapper.selectLifeSupplierInfoById(supplierId);
        return AjaxResult.success(supplierInfo);
    }

    @PostMapping("/cancelSubscribe")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult cancelSubscribe(@RequestBody AppOrderInfo appOrderInfo) {
        String orderId = appOrderInfo.getOrderId();
        LifeOrder order = lifeOrderMapper.selectLifeOrderById(orderId);
        order.setStatus(LifeServiceConstants.ORDER_STATUS_CANCEL);
        order.setUpdateTime(new Date());
        order.setUpdateBy(order.getUserId());
        dealWorkClassStock(order.getWorkClassId(), false);
        lifeOrderMapper.updateLifeOrder(order);
        return AjaxResult.success();
    }

    @PostMapping("/delete")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult delete(@RequestBody AppOrderInfo appOrderInfo) {
        String orderId = appOrderInfo.getOrderId();
        LifeOrder order = lifeOrderMapper.selectLifeOrderById(orderId);
        if (LifeServiceConstants.ORDER_STATUS_NOMAL == order.getStatus()) {
            return AjaxResult.error("删除失败，订单状态错误");
        }
        order.setStatus(LifeServiceConstants.ORDER_STATUS_DELETED);
        lifeOrderMapper.updateLifeOrder(order);
        return AjaxResult.success();
    }

    @PostMapping("/givescore")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult givescore(@RequestBody AppOrderInfo appOrderInfo) {
        String orderId = appOrderInfo.getOrderId();
        BigDecimal score = appOrderInfo.getScore();
        LifeOrder order = lifeOrderMapper.selectLifeOrderById(orderId);
        if (null == order) {
            return AjaxResult.error("订单信息错误！");
        }
        order.setScore(score);
        order.setUpdateTime(new Date());
        lifeOrderMapper.updateLifeOrder(order);
        return AjaxResult.success();
    }

    @PostMapping("/complete")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult complete(@RequestBody AppOrderInfo appOrderInfo) {
        String orderId = appOrderInfo.getOrderId();
        LifeOrder order = lifeOrderMapper.selectLifeOrderById(orderId);
        if (null == order) {
            return AjaxResult.error("订单信息错误！");
        }
        if (order.getStatus() != LifeServiceConstants.ORDER_STATUS_NOMAL) {
            return AjaxResult.error("订单状态错误！");
        }
        order.setStatus(LifeServiceConstants.ORDER_STATUS_COMPLETE);
        order.setUpdateTime(new Date());
        lifeOrderMapper.updateLifeOrder(order);
        return AjaxResult.success();
    }

    @PostMapping("/reSubscribe")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult reSubscribe(@RequestBody AppOrderInfo appOrderInfo) {
        String orderId = appOrderInfo.getOrderId();
        LifeOrder order = lifeOrderMapper.selectLifeOrderById(orderId);
        order.setStatus(LifeServiceConstants.ORDER_STATUS_NOMAL);
        order.setUpdateTime(new Date());
        order.setUpdateBy(order.getUserId());
        order.setGuestName(appOrderInfo.getGuestName());
        order.setGuestPhone(appOrderInfo.getGuestPhone());
        order.setGuestRemark(appOrderInfo.getGuestRemark());
        dealWorkClassStock(order.getWorkClassId(), true);
        lifeOrderMapper.updateLifeOrder(order);
        LifeSupplierInfo supplierInfo = lifeSupplierInfoMapper.selectLifeSupplierInfoById(appOrderInfo.getSupplierId());
        return AjaxResult.success(supplierInfo);
    }

    public void dealWorkClassStock(String workClassId, boolean isSubscribe) {
        String lockKey = LifeServiceConstants.WORK_CLASS_STOCK_LOCK + workClassId;
        try {
            if (redisLockUtil.getLock(lockKey)) {
                LifeWorkClass dbLifeWorkClass = lifeWorkClassMapper.selectLifeWorkClassById(workClassId);
                String scheduleId = dbLifeWorkClass.getScheduleId();
                Integer stock = dbLifeWorkClass.getStock();
                if (isSubscribe && stock < 1) {
                    throw new ServiceException("当前时间段已约满", 500);
                }
                if (isSubscribe) {
                    stock = stock - 1;
                } else {
                    stock = stock + 1;
                }
                dbLifeWorkClass.setStock(stock);
                lifeWorkClassMapper.updateLifeWorkClass(dbLifeWorkClass);
                LifeWorkClass queryList = new LifeWorkClass();
                queryList.setScheduleId(scheduleId);
                List<LifeWorkClass> cachedLifeWorkClassList = lifeWorkClassMapper.selectLifeWorkClassList(queryList);
                String cacheKey = LifeServiceConstants.WORK_CLASS_BY_SCHEID_CACHE_PREFIX + scheduleId;
                redisCache.deleteObject(cacheKey);
                redisCache.setCacheList(cacheKey, cachedLifeWorkClassList);
            } else {
                throw new ServiceException("当前时间段繁忙，请稍后预约", 500);
            }
        } catch (Exception e) {
            log.error("deal stock failed!error is {}", e);
            throw e;
        } finally {
            redisLockUtil.releaseLock(lockKey);
        }
    }

}
